package core.remote;

import core.GlobalConfig;
import java.io.IOException;
import java.net.*;
import java.util.UUID;
import core.Main;
import java.util.List;
import tools.FucLib;
import tools.Logger;

/**
 * Init Remote Console
 * @author dcrm
 */
public class CoreRC implements Runnable {

    private int clientCount = 0;
    private ServerSocket server = null;
    private Thread thread = null;
    private ClientRC clients[] = new ClientRC[50];
    
    private boolean icq=false;
    private boolean jabber=false;
    private boolean phpbb=false;

    private String icq_pwd="";
    private String jid_pwd="";
    private String phpbb_pwd="";


    /**
     * Start Remote console on localhost
     * @param port - Port
     */
    public CoreRC(int port) {
        this(port, "");
    }

    /**
     * Start Remote console
     * @param port - Port
     * @param host - Server host/ip
     */
    public CoreRC(int port,String host) {
        try {
            Main.pr("Bind: "+port,true);
            server = (!host.isEmpty())?new ServerSocket(port,0,InetAddress.getByName(host)):new ServerSocket(port);
            Main.pr("\nStarted OK: "+server+" ",true);
            start();
        } catch (Exception ex) {Logger.writelnErr("Can't bind: "+port+"; "+ex.getMessage());}
    }


    public void run() {
        try {
            while(thread != null) {
                try {
                    Main.pr("\nWaiting client...\n");
                    addThread(server.accept());
                } catch (IOException ex) {Logger.writelnErr("Server accert Error:"+ex.getMessage()); stop();}
            }
        } catch (Exception ex0) {Logger.writelnErr("Server run Error: "+ex0.getLocalizedMessage());}
    }
    
    public synchronized void start() {
        try {
            if (thread==null){
                thread = new Thread(this);
                thread.setName("ChatServer");
                thread.start();
            }
        } catch (Exception ex) {Logger.writelnErr("Error(start): "+ex.getLocalizedMessage());}
    }
    
    public synchronized void stop() {
        try {
            if (thread!=null) {
                thread.stop();
                thread=null;
            }
        } catch (Exception ex) {Logger.writelnErr("Error(stop): "+ex.getLocalizedMessage());}
    }

    private synchronized int findClient(int ID) {
        try {
            for (int i=0;i<clientCount;i++) { if (clients[i].getID()==ID) return i; }
        } catch (Exception ex) {Logger.writelnErr("Error(findClient): "+ex.getLocalizedMessage()); return -1;}
        return -1;
    }

    private synchronized void sendAllClient(String str) {
        try {
            for (int i=0;i<clientCount;i++) { clients[i].send(str); }
        } catch (Exception ex) {Logger.writelnErr("Error(sendAll): "+ex.getLocalizedMessage());}
    }

    public synchronized void handle(int ID,String input) {
        try {
            
           if (input.equals("#getuserlist")) {
                String name="";
                String ntmp[]=null;
                List<List<String>> list = null;
                for (int i=0;i<clientCount;i++) {
                    name+=(clients[i].isADM())?"a@":"u@";
                    if (!clients[findClient(ID)].isADM()) {
                        list = FucLib.preg_match_all_toArrList("[0-9]{1,3}:([0-9]{4,5})", "iu", clients[i].getName());
                        ntmp=list.get(0).get(0).split(":");
                        if (ntmp.length==2) {name+=ntmp[1]+"|";}
                    } else name+=clients[i].getName()+"|";
                } name="#getuserlist|"+name;
                clients[findClient(ID)].send(name);
            }
            if (input.equals("#getusercount")) {
                clients[findClient(ID)].send(Integer.toString(clientCount));
            }

            if (input.equals(".bye")) {
                clients[findClient(ID)].send(".bye");
                remove(ID);
            } else
            if (input.equals(".hi")) {
                clients[findClient(ID)].send("HiHi!");
            } else
            if (input.startsWith(".adm")) {
                if (input.length()>=5) {
                    String msg_0=input.substring(5).trim();
                    if (msg_0.startsWith("login") && (msg_0.length()>=5)) {
                        String msg_1=msg_0.substring(6).trim();
                        if (FucLib.getMD5(msg_1).equals(GlobalConfig.getPWD(GlobalConfig.TYPE_CHAT))) {clients[findClient(ID)].isADM(true);}
                        sendResultLogin(ID, GlobalConfig.TYPE_CHAT);
                    }
                }
            } else
            if (clients[findClient(ID)].isADM()) {
                if (input.startsWith(".login")) {
                    if (input.length()>=6) {
                        String msg_0=input.substring(6).trim();
                        try {
                            String msg_1[]=msg_0.split(" ");
                            if (msg_1.length>=2){
                                if (msg_1[0].equals("icq")) {
                                    if (FucLib.getMD5(msg_1[1]).equals(GlobalConfig.getPWD(GlobalConfig.TYPE_ICQ))) {icq=true; icq_pwd=msg_1[1]; sendResultLogin(ID, GlobalConfig.TYPE_ICQ);}
                                }

                                else if (msg_1[0].equals("jid")) {
                                    if (FucLib.getMD5(msg_1[1]).equals(GlobalConfig.getPWD(GlobalConfig.TYPE_XMPP))) {jabber=true; jid_pwd=msg_1[1]; sendResultLogin(ID, GlobalConfig.TYPE_XMPP);}
                                }
                                
                                else if (msg_1[0].equals("phpbb")) {
                                    if (FucLib.getMD5(msg_1[1]).equals(GlobalConfig.getPWD(GlobalConfig.TYPE_PHPBB))) {phpbb=true; phpbb_pwd=msg_1[1]; sendResultLogin(ID, GlobalConfig.TYPE_PHPBB);}
                                }
                            } else sendAdminMessage(ID, "Correct: .login [icq/jid/phpbb] [pwd]\rNext: .start");
                        } catch (Exception ex) {ex.printStackTrace();}
                    }
                }

                if (input.equals(".start")) {
                    try {
                        if(icq) {Main.setPWD(icq_pwd, GlobalConfig.TYPE_ICQ);}
                        if(jabber) {Main.setPWD(jid_pwd, GlobalConfig.TYPE_XMPP);}
                        if(phpbb) {Main.setPWD(phpbb_pwd, GlobalConfig.TYPE_PHPBB);}
                        if (icq || jabber || phpbb) {Main.starter(true);} else sendAdminMessage(ID, "Nothing start :(");
                    } catch (Exception ex) {ex.printStackTrace();}
                }
                if (input.startsWith(".stop")) {
                    Main.stoper();
                    clients[findClient(ID)].send("Stop OK.");
                }
                if (input.startsWith(".regroup")) {
                    clients[findClient(ID)].send(FucLib.toTranslite(FucLib.getAllGroup(Main.GROUP, 10)));
                    clients[findClient(ID)].send("Groups reloaded!");
                }
                if (input.startsWith(".repost")) {
                    Main.poster();
                    clients[findClient(ID)].send("RePosting OK!");
                }
                if (input.startsWith(".restart")) {
                    Main.stoper();
                    Main.starter(true);
                    clients[findClient(ID)].send("Restart OK!");
                }
                if (input.startsWith(".state")) {
                    if (Main.CORE_INF!=null) { clients[findClient(ID)].send(FucLib.toTranslite(Main.CORE_INF.getState()));}
                        else clients[findClient(ID)].send("Core ICQ not runnig!");
                    if (Main.CORE_XMPP!=null) { clients[findClient(ID)].send(FucLib.toTranslite(Main.CORE_XMPP.getState()));}
                        else clients[findClient(ID)].send("Core XMPP not runnig!");
                }
                if (input.startsWith(".logout")) {
                    clients[findClient(ID)].isADM(false);
                    clients[findClient(ID)].send("Logout... OK.");
                }
                if (input.startsWith(".shutdown")) {
                    Main.stoper();
                    sendAllClient("Infhell let's go in other world...");
                    Main.exit();
                }
            } else if (!input.startsWith(".") && !input.startsWith("#")) {
                for(int i=0;i<clientCount;i++) { clients[i].send(ID+": "+input); }
            }
        } catch (Exception ex0) {Logger.writelnErr("Error in message: "+ ex0.getMessage());}
    }
    
    private synchronized void sendResultLogin(int ID, int TYPE) {
        String msg="";
        switch (TYPE) {
            case GlobalConfig.TYPE_ICQ: msg="ICQ login ["+Boolean.toString(icq)+"]"; break;
            case GlobalConfig.TYPE_XMPP: msg="Jabber login ["+Boolean.toString(jabber)+"]"; break;
            case GlobalConfig.TYPE_PHPBB: msg="Phpbb login ["+Boolean.toString(phpbb)+"]"; break;
            case GlobalConfig.TYPE_CHAT: msg="Chat login ["+Boolean.toString(clients[findClient(ID)].isADM())+"]"; break;
            default: msg="No login"; break;
        }
        clients[findClient(ID)].send(msg);
    }

    private synchronized void sendAdminMessage(int ID, String msg) {
        int id = findClient(ID);
        if (clients[id].isADM()){clients[id].send(msg);}
    }
    
    public synchronized void remove(int ID) {
        try {
        int pos = findClient(ID);
        if (pos>=0) {
            ClientRC toTerminate = clients[pos];
            if (pos<clientCount) {
                for (int i=pos+1;i<clientCount; i++)
                    clients[i-1]=clients[i];
                clientCount--;
                toTerminate.close();}
                toTerminate.stop();
            }
        } catch (Exception ex) {Logger.writelnErr("Error closing thread: "+ ex.getMessage());}
    }

    public synchronized void addThread(Socket socket) {
        try {
            if (clientCount<clients.length) {
                Main.pr("\nClient++: "+socket+"\n",true);
                clients[clientCount] = new ClientRC(this, socket);
                clients[clientCount].setName("TCP["+socket.getRemoteSocketAddress().toString()+"]$["+UUID.randomUUID()+"]");
                clients[clientCount].open();
                clients[clientCount].start();
                clientCount++;
            } else Main.pr("Client refused: maximum" + clients.length + " reached.",true);
        } catch (Exception ex0) {Logger.writelnErr("Error thread: "+ ex0.getMessage());}
    }

}
